<!DOCTYPE html>


<html lang="en">
  

    <head>
      <meta charset="utf-8" />
        
      <meta
        name="viewport"
        content="width=device-width, initial-scale=1, maximum-scale=1"
      />
      <title>《JavaScript高级程序设计》- 第五章：基本引用类型 |  欢迎</title>
  <meta name="generator" content="hexo-theme-ayer">
      
      <link rel="shortcut icon" href="/favicon.ico" />
       
<link rel="stylesheet" href="/dist/main.css">

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/gh/Shen-Yu/cdn/css/remixicon.min.css"
      />
      
<link rel="stylesheet" href="/css/custom.css">
 
      <script src="https://cdn.jsdelivr.net/npm/pace-js@1.0.2/pace.min.js"></script>
       
 

      <link
        rel="stylesheet"
        href="https://cdn.jsdelivr.net/npm/@sweetalert2/theme-bulma@5.0.1/bulma.min.css"
      />
      <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11.0.19/dist/sweetalert2.min.js"></script>

      <!-- mermaid -->
      
      <style>
        .swal2-styled.swal2-confirm {
          font-size: 1.6rem;
        }
      </style>
    <link rel="alternate" href="/atom.xml" title="欢迎" type="application/atom+xml">
</head>
  </html>
</html>


<body>
  <div id="app">
    
      
    <main class="content on">
      <section class="outer">
  <article
  id="post-JavaScript学习/《JavaScript高级程序设计》- 第五章：基本引用类型"
  class="article article-type-post"
  itemscope
  itemprop="blogPost"
  data-scroll-reveal
>
  <div class="article-inner">
    
    <header class="article-header">
       
<h1 class="article-title sea-center" style="border-left:0" itemprop="name">
  《JavaScript高级程序设计》- 第五章：基本引用类型
</h1>
 

      
    </header>
     
    <div class="article-meta">
      <a href="/2022/02/13/JavaScript%E5%AD%A6%E4%B9%A0/%E3%80%8AJavaScript%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E3%80%8B-%20%E7%AC%AC%E4%BA%94%E7%AB%A0%EF%BC%9A%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/" class="article-date">
  <time datetime="2022-02-13T03:50:32.000Z" itemprop="datePublished">2022-02-13</time>
</a> 
  <div class="article-category">
    <a class="article-category-link" href="/categories/JavaScript%E5%AD%A6%E4%B9%A0/">JavaScript学习</a>
  </div>
  
<div class="word_count">
    <span class="post-time">
        <span class="post-meta-item-icon">
            <i class="ri-quill-pen-line"></i>
            <span class="post-meta-item-text"> Word count:</span>
            <span class="post-count">3.8k</span>
        </span>
    </span>

    <span class="post-time">
        &nbsp; | &nbsp;
        <span class="post-meta-item-icon">
            <i class="ri-book-open-line"></i>
            <span class="post-meta-item-text"> Reading time≈</span>
            <span class="post-count">15 min</span>
        </span>
    </span>
</div>
 
    </div>
      
    <div class="tocbot"></div>




  
    <div class="article-entry" itemprop="articleBody">
       
  <h2 id="基本引用类型"><a href="#基本引用类型" class="headerlink" title="基本引用类型"></a>基本引用类型</h2><blockquote>
<p>基本概念：</p>
</blockquote>
<ul>
<li><code>引用值</code>：又称<code>对象</code>，是某个<code>特定引用类型</code>的<code>实例</code>。</li>
<li><code>引用类型</code>：又称<code>对象定义</code>，引用类型描述了<code>对象</code>的<code>属性</code>和<code>方法</code>。</li>
<li>新对象通过<code>new</code>操作符后面跟一个<code>构造函数</code>来创建。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> now = <span class="keyword">new</span> <span class="built_in">Date</span>();</span><br></pre></td></tr></table></figure>
<blockquote>
<p>注意：虽然<code>引用类型</code>有点像<code>类</code>，但是和<code>类</code>不是同一个概念。</p>
</blockquote>
</li>
</ul>
<h3 id="5-1-Date"><a href="#5-1-Date" class="headerlink" title="5.1 Date"></a>5.1 Date</h3><blockquote>
<p>怎样使用？<br>  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> timeFormat = <span class="number">2</span>/<span class="number">12</span>/<span class="number">2022</span>;</span><br><span class="line"><span class="keyword">let</span> now = <span class="keyword">new</span> <span class="built_in">Date</span>(timeFormat);</span><br></pre></td></tr></table></figure><br>可使用的timeFormat有多少种？</p>
</blockquote>
<ul>
<li>月/日/年</li>
<li>月名/日,年</li>
<li>周几 月名 日 年 时:分:秒 时区</li>
<li>YYYY-MM-DDTHH:mm:ss:sssZ</li>
</ul>
<h4 id="5-1-1-继承的方法"><a href="#5-1-1-继承的方法" class="headerlink" title="5.1.1 继承的方法"></a>5.1.1 继承的方法</h4><blockquote>
<p>以下所继承的方法，可能会因浏览器而有不同</p>
</blockquote>
<ul>
<li>toLocaleString()：返回日期时间</li>
<li>toString()：返回<code>带有时区</code>的日期时间</li>
<li>valueOf()：返回日期的毫秒表示</li>
</ul>
<h4 id="5-1-2-日期格式化方法"><a href="#5-1-2-日期格式化方法" class="headerlink" title="5.1.2 日期格式化方法"></a>5.1.2 日期格式化方法</h4><blockquote>
<p>在<code>Date</code>类型中，有几个专门<code>格式化日期</code>的方法，返回值都是<code>字符串</code></p>
</blockquote>
<ul>
<li>toDateString()显示日期中的周几、 月、 日、 年（格式特定于实现） ；</li>
<li>toTimeString()显示日期中的时、 分、 秒和时区（格式特定于实现） ；</li>
<li>toLocaleDateString()显示日期中的周几、 月、 日、 年（格式特定于实现和地区） ；</li>
<li>toLocaleTimeString()显示日期中的时、 分、 秒（格式特定于实现和地区） ；</li>
<li>toUTCString()显示完整的UTC日期（格式特定于实现） 。 </li>
</ul>
<h4 id="5-1-3-日期、时间组件方法"><a href="#5-1-3-日期、时间组件方法" class="headerlink" title="5.1.3 日期、时间组件方法"></a>5.1.3 日期、时间组件方法</h4><ul>
<li><code>getTime()</code>    返回日期的毫秒表示；与valueOf()相同</li>
<li><code>setTime(milliseconds)</code>    设置日期的毫秒表示，从而修改整个日期</li>
<li><code>getFullYear()</code>    返回4位数年（即2019而不是19）</li>
<li><code>getUTCFullYear()</code>    返回UTC日期的4位数年</li>
<li><code>setFullYear(year)</code>    设置日期的年（year必须是4位数）</li>
<li><code>setUTCFullYear(year)</code>    设置UTC日期的年（year必须是4位数）</li>
<li><code>getMonth()</code>    返回日期的月（0表示1月，11表示12月）</li>
<li><code>getUTCMonth()</code>    返回UTC日期的月（0表示1月，11表示12月）</li>
<li><code>setMonth(month)</code>    设置日期的月（month为大于0的数值，大于11加年）</li>
<li><code>setUTCMonth(month)</code>    设置UTC日期的月（month为大于0的数值，大于11加年）</li>
<li><code>getDate()</code>    返回日期中的日（1~31）</li>
<li><code>getUTCDate()</code>    返回UTC日期中的日（1~31）</li>
<li><code>setDate(date)</code>    设置日期中的日（如果date大于该月天数，则加月）</li>
<li><code>setUTCDate(date)</code>    设置UTC日期中的日（如果date大于该月天数，则加月）</li>
<li><code>getDay()</code>    返回日期中表示周几的数值（0表示周日，6表示周六）</li>
<li><code>getUTCDay()</code>    返回UTC日期中表示周几的数值（0表示周日，6表示周六）</li>
<li><code>getHours()</code>    返回日期中的时（0~23）</li>
<li><code>getUTCHours()</code>    返回UTC日期中的时（0~23）</li>
<li><code>setHours(hours)</code>    设置日期中的时（如果hours大于23，则加日）</li>
<li><code>setUTCHours(hours)</code>    设置UTC日期中的时（如果hours大于23，则加日）</li>
<li><code>getMinutes()</code>    返回日期中的分（0~59）</li>
<li><code>getUTCMinutes()</code>    返回UTC日期中的分（0~59）</li>
<li><code>setMinutes(minutes)</code>    设置日期中的分（如果minutes大于59，则加时）</li>
<li><code>setUTCMinutes(minutes)</code>    设置UTC日期中的分（如果minutes大于59，则加时）</li>
<li><code>getSeconds()</code>    返回日期中的秒（0~59）</li>
<li><code>getUTCSeconds()</code>    返回UTC日期中的秒（0~59）</li>
<li><code>setSeconds(seconds)</code>    设置日期中的秒（如果seconds大于59，则加分）</li>
<li><code>setUTCSeconds(seconds)</code>    设置UTC日期中的秒（如果seconds大于59，则加分）</li>
<li><code>getMilliseconds()</code>    返回日期中的毫秒</li>
<li><code>getUTCMilliseconds()</code>    返回UTC日期中的毫秒</li>
<li><code>setMilliseconds(milliseconds)</code>    设置日期中的毫秒</li>
<li><code>setUTCMilliseconds(milliseconds)</code>     设置UTC日期中的毫秒</li>
<li><code>getTimezoneOffset()</code>    返回以分钟计的UTC与本地时区的偏移量（如美国EST即“东部标准时间”返回300，进入夏令时的地区可能有所差异）</li>
</ul>
<h3 id="5-2-RegExp"><a href="#5-2-RegExp" class="headerlink" title="5.2 RegExp"></a>5.2 RegExp</h3><blockquote>
<p>RegExp用来支持<code>正则表达式</code></p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 类似Perl的简洁语法创建</span></span><br><span class="line"><span class="keyword">let</span> expression1 = <span class="regexp">/pattern/</span>flags;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 上下两种定义方法是等效的</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// RegExp语法创建</span></span><br><span class="line"><span class="keyword">let</span> expression2 = <span class="keyword">new</span> <span class="built_in">RegExp</span>(pattern,flags);</span><br></pre></td></tr></table></figure>


<blockquote>
<p>pattern就是<code>正则表达式</code>，而flags有什么值？</p>
</blockquote>
<ul>
<li>g：全局模式，表示查找字符串的全部内容，而不是找到第一个匹配的内容就结束。</li>
<li>i：不区分大小写，表示在查找匹配时忽略pattern和字符串的大小写。</li>
<li>m：多行模式，表示查找到一行文本末尾时会继续查找。</li>
<li>y：粘附模式，表示只查找从lastIndex开始及之后的字符串。</li>
<li>u：Unicode模式，启用Unicode匹配。</li>
<li>s：dotAll模式，表示元字符.匹配任何字符（包括\n或\r）。</li>
</ul>
<h4 id="5-2-1-RegExp实例属性"><a href="#5-2-1-RegExp实例属性" class="headerlink" title="5.2.1 RegExp实例属性"></a>5.2.1 RegExp实例属性</h4><blockquote>
<p>每个<code>RegExp</code>实例都具有如下<code>属性</code>：</p>
</blockquote>
<ul>
<li>global：布尔值，表示是否设置了g标记。</li>
<li>ignoreCase：布尔值，表示是否设置了i标记。</li>
<li>unicode：布尔值，表示是否设置了u标记。</li>
<li>sticky：布尔值，表示是否设置了y标记。</li>
<li>lastIndex：整数，表示在源字符串中下一次搜索的开始位置，始终从0开始。</li>
<li>multiline：布尔值，表示是否设置了m标记。</li>
<li>dotAll：布尔值，表示是否设置了s标记。</li>
<li>source：正则表达式的字面量字符串（不是传给构造函数的模式字符串），没有开头和结尾的斜杠。</li>
<li>flags：正则表达式的标记字符串。始终以字面量而非传入构造函数的字符串模式形式返回（没有前后斜杠）。</li>
</ul>
<h4 id="5-2-2-RegExp实例方法"><a href="#5-2-2-RegExp实例方法" class="headerlink" title="5.2.2 RegExp实例方法"></a>5.2.2 RegExp实例方法</h4><blockquote>
<p>RegExp的实例方法主要是<code>exec()</code>;主要用于<code>配合捕获组</code>使用。</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;cat, bat, sat, fat&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> pattern = <span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="regexp">/.at/</span>,<span class="string">&#x27;g&#x27;</span>);</span><br><span class="line"><span class="keyword">let</span> results = pattern.exec(text);</span><br><span class="line"><span class="built_in">console</span>.log(results); <span class="comment">//  [ &#x27;cat&#x27;, index: 0, input: &#x27;cat, bat, sat, fat&#x27;, groups: undefined ]</span></span><br><span class="line">results = pattern.exec(text);</span><br><span class="line"><span class="built_in">console</span>.log(results); <span class="comment">//  [ &#x27;bat&#x27;, index: 5, input: &#x27;cat, bat, sat, fat&#x27;, groups: undefined ]</span></span><br><span class="line">results = pattern.exec(text);</span><br><span class="line"><span class="built_in">console</span>.log(results); <span class="comment">//  [ &#x27;sat&#x27;, index: 10, input: &#x27;cat, bat, sat, fat&#x27;, groups: undefined ]</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>对于<code>exec()</code>,如果找到了匹配项，则会返回<code>包含第一个匹配信息</code>的<code>数组</code>。反之则返回<code>null</code></p>
</blockquote>
<h4 id="5-2-3-RegExp构造函数属性"><a href="#5-2-3-RegExp构造函数属性" class="headerlink" title="5.2.3 RegExp构造函数属性"></a>5.2.3 RegExp构造函数属性</h4><blockquote>
<p>在其他语言中，可以叫做<code>静态属性</code>。RegExp的静态属性有两种访问方式：<code>全名访问</code>、<code>简写访问</code>。</p>
</blockquote>
<blockquote>
<p>注意：这些<code>构造函数属性</code>,没有任何Web标准出处，所以不要在生产环境中使用。【好像已经弃用了】</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">  <span class="keyword">let</span> text = <span class="string">&quot;this has been a short summer&quot;</span>;</span><br><span class="line">  <span class="keyword">let</span> pattern = <span class="regexp">/(.)hort/g</span>;</span><br><span class="line">  <span class="keyword">if</span> (pattern.test(text)) &#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">RegExp</span>[<span class="string">&quot;$_&quot;</span>]);  <span class="comment">// 简写用法</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">RegExp</span>.input); <span class="comment">// this has been a short summer</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">RegExp</span>.leftContext); <span class="comment">// this has been a</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">RegExp</span>.rightContext); <span class="comment">// summer</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">RegExp</span>.lastMatch); <span class="comment">// short</span></span><br><span class="line">  <span class="built_in">console</span>.log(<span class="built_in">RegExp</span>.lastParen); <span class="comment">// s</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<blockquote>
<p><code>静态属性</code>概括如下：<br>  <table><br>    <tr><br>      <td>全名</td><td>简写</td><td>说明</td><br>    </tr><br>    <tr><br>      <td>input</td><td>$_</td><td>最后搜索的字符串</td><br>    </tr><br>    <tr><br>      <td>lastMatch</td><td>$&amp;</td><td>最后匹配的文本</td><br>    </tr><br>    <tr><br>      <td>lastParen</td><td>$+</td><td>最后匹配的捕获组</td><br>    </tr><br>    <tr><br>      <td>leftContext</td><td>$`</td><td>input字符串左边的文本</td><br>    </tr><br>    <tr><br>      <td>rightContext</td><td>$’</td><td>input字符串右边的文本</td><br>    </tr><br>  </table></p>
</blockquote>
<h3 id="5-3-原始包装类型"><a href="#5-3-原始包装类型" class="headerlink" title="5.3 原始包装类型"></a>5.3 原始包装类型</h3><blockquote>
<p>ECMAScript提供3种特殊的引用类型：Boolean、Number和String。使其既有<code>引用类型特点</code>，又有<code>原始类型的特殊行为</code>。</p>
</blockquote>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 表面上：</span></span><br><span class="line"><span class="keyword">let</span> s1 = <span class="string">&#x27;hello world&#x27;</span>; </span><br><span class="line"><span class="keyword">let</span> s2 = s1.substring(<span class="number">2</span>);</span><br><span class="line"><span class="built_in">console</span>.log(s1);</span><br><span class="line"><span class="built_in">console</span>.log(s2);</span><br></pre></td></tr></table></figure>
<blockquote>
<p>为什么s1是原始值，但是可以使用<code>substring()</code>方法？</p>
</blockquote>
<ul>
<li>因为每次使用原始值的<code>方法</code>和<code>属性</code>的时候，后台会创建一个对于的原始包装类型的对象，暴露原始值的操作方法，然后销毁对象。<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 实际上：</span></span><br><span class="line"> <span class="keyword">let</span> s1 = <span class="string">&#x27;hello world&#x27;</span>; </span><br><span class="line"> <span class="keyword">let</span> s2 = s1.substring(<span class="number">2</span>);</span><br><span class="line"> <span class="comment">/*  后台中操作</span></span><br><span class="line"><span class="comment"> let temp = new String(s1);</span></span><br><span class="line"><span class="comment"> s2 = temp.substring(2);</span></span><br><span class="line"><span class="comment"> temp = null;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="built_in">console</span>.log(s1);</span><br><span class="line"> <span class="built_in">console</span>.log(s2);</span><br></pre></td></tr></table></figure>
<blockquote>
<p>注意事项：</p>
</blockquote>
</li>
</ul>
<ol>
<li><code>Number()</code> 和 <code>new Number()</code>有什么区别？ <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> value = <span class="string">&quot;25&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> number = <span class="built_in">Number</span>(value); <span class="comment">// 转型函数</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> number); <span class="comment">// &quot;number&quot;</span></span><br><span class="line"><span class="keyword">let</span> obj = <span class="keyword">new</span> <span class="built_in">Number</span>(value); <span class="comment">// 构造函数</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> obj); <span class="comment">// &quot;object&quot;</span></span><br></pre></td></tr></table></figure></li>
<li><code>原始值包装对象</code>都会转化为<code>true</code> <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> falseObject = <span class="keyword">new</span> <span class="built_in">Boolean</span>(<span class="literal">false</span>);</span><br><span class="line"><span class="keyword">let</span> result = falseObject &amp;&amp; <span class="literal">true</span>;</span><br><span class="line"><span class="built_in">console</span>.log(result);    <span class="comment">// 输出true</span></span><br></pre></td></tr></table></figure>
<blockquote>
<pre><code>所以不推荐显示创建`原始值包装对象`，但是它们对于操作原始值的功能很重要。
</code></pre>
</blockquote>
</li>
</ol>
<h4 id="5-3-1-Boolean"><a href="#5-3-1-Boolean" class="headerlink" title="5.3.1 Boolean"></a>5.3.1 Boolean</h4><blockquote>
<p>Boolean类型重写了<code>valueOf() toLocaleString() toString()</code></p>
</blockquote>
<ul>
<li><code>valueOf()</code>:返回对象表示的<code>原始数值</code></li>
<li>其他两个返回<code>字符串表示</code></li>
</ul>
<h4 id="5-3-2-Number"><a href="#5-3-2-Number" class="headerlink" title="5.3.2 Number"></a>5.3.2 Number</h4><blockquote>
<p>Number与上面Boolean说的一样。</p>
</blockquote>
<blockquote>
<p>Number中一些方法：<br> <table><br>    <tr><br>      <td>方法</td><td>参数</td><td>说明</td><br>    </tr><br>    <tr><br>      <td>toFixed()</td><td>一个参数：保留的小数点位数【会自动四舍五入】</td><td>返回包含指定小数点位数的数值字符串</td><br>    </tr><br>    <tr><br>      <td>toExponential()</td><td>一个参数：表示结果中小数的位数</td><td>返回以科学记数法表示的数值字符串</td><br>    </tr><br>    <tr><br>      <td>toPrecision()</td><td>一个参数：总位数（不包括指数）</td><td>返回合理的数字</td><br>    </tr><br>    <tr><br>      <td>isInteger()</td><td>一个参数：待判断的数值</td><td>判断是不是合理的整数，返回布尔值</td><br>    </tr><br>  </table></p>
</blockquote>
<h4 id="5-3-3-String"><a href="#5-3-3-String" class="headerlink" title="5.3.3 String"></a>5.3.3 String</h4><blockquote>
<p>String是对应字符串的应用类型，具有3个继承的方法：<code>valueOf()、toLocaleString()、toString()</code>,返回对象的原始字符串值。</p>
</blockquote>
<blockquote>
<p>关于字符编码的一些属性和方法：</p>
</blockquote>
<ol>
<li><code>length</code>属性表示字符串包含多少16位码元;<blockquote>
<p>JavaScript字符串由<code>16位码元</code>组成，每一个<code>16位码元</code>对应一个字符。<br /><br>注意：对于<code>基本多语言平面（BMP）</code>而言，需要采用<code>两个16位码元</code>来表达，又称为<code>代理对</code>;</p>
</blockquote>
</li>
<li><code>charAt()</code>方法：返回给定<code>索引位置</code>的<code>字符</code>;</li>
<li><code>charCodeAt()</code>方法：返回给定<code>索引位置</code>的<code>字符编码</code>;</li>
<li><code>fromCharCode()</code>方法：返回给定的UTF-16编码字符</li>
</ol>
<blockquote>
<p>关于字符串的操作方法：</p>
</blockquote>
<ol>
<li><code>concat()</code>：用于字符串的拼接。 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> string1 = <span class="string">&quot;Hello,&quot;</span></span><br><span class="line"><span class="built_in">console</span>.log(string1.concat(<span class="string">&quot;world!&quot;</span>));  <span class="comment">// Hello,world!</span></span><br></pre></td></tr></table></figure></li>
<li><code>slice(start[,end])</code>：返回 [start,end)之间的元素，将传入的负参数与字符串长度相加。 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> test = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(test.slice(<span class="number">3</span>));   <span class="comment">// lo world</span></span><br><span class="line"><span class="built_in">console</span>.log(test.slice(-<span class="number">3</span>));  <span class="comment">// rld</span></span><br></pre></td></tr></table></figure></li>
<li><code>subString(start[,length])</code>：返回从start开始，长度为length的字符串; 把所有的负值置为0； <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> test = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(test.substring(<span class="number">3</span>));    <span class="comment">// lo world</span></span><br><span class="line"><span class="built_in">console</span>.log(test.substring(-<span class="number">1</span>));    <span class="comment">// hello world</span></span><br></pre></td></tr></table></figure></li>
</ol>
<blockquote>
<p>关于字符位置的方法：</p>
</blockquote>
<ol>
<li>indexOf(aimString[,startPosition])：<code>从前往后</code>找给定字符串，未找到则返回-1； <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(text.indexOf(<span class="string">&quot;o&quot;</span>)); <span class="comment">// 4</span></span><br><span class="line"><span class="built_in">console</span>.log(text.indexOf(<span class="string">&quot;o&quot;</span>,<span class="number">6</span>)); <span class="comment">// 7</span></span><br></pre></td></tr></table></figure></li>
<li>lastIndexOf(aimString[,startPosition])：<code>从后往前</code>找给定字符串并返回位置，未找到则返回-1； <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;hello world&quot;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(text.lastIndexOf(<span class="string">&quot;o&quot;</span>)); <span class="comment">// 7</span></span><br><span class="line"><span class="built_in">console</span>.log(text.lastIndexOf(<span class="string">&quot;o&quot;</span>,<span class="number">6</span>)); <span class="comment">// 4</span></span><br></pre></td></tr></table></figure></li>
</ol>
<blockquote>
<p>关于字符串包含的方法：</p>
</blockquote>
<ol>
<li>startsWith(aimString[,startPosition])：判断是否以指定字符串开头；</li>
<li>endsWith(aimString[,startPosition])：判断是否以指定字符串结尾；</li>
<li>includes(aimString[,startPosition])：判断是否包括指定字符串；</li>
</ol>
<blockquote>
<p>关于字符串删除前后空格的方法</p>
</blockquote>
<ol>
<li>trim()：删除字符串前、后的空格符</li>
<li>trimLeft()：删除字符串前面的空格符</li>
<li>trimRight()：删除字符串后面的空格符</li>
</ol>
<blockquote>
<p>复制字符串</p>
</blockquote>
<ol>
<li>repeat(times)：返回复制times次后的字符串。 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> test = <span class="string">&#x27;hello&#x27;</span>;</span><br><span class="line"><span class="built_in">console</span>.log( test.repeat(<span class="number">4</span>) );  <span class="comment">// hellohellohellohello</span></span><br></pre></td></tr></table></figure></li>
<li>padStart(length[,charType]):复制<code>length</code>长度的字符串，如果长度不够，则在前面补充<code>charType</code>;[默认为空格] <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> test = <span class="string">&#x27;hello&#x27;</span>;</span><br><span class="line"><span class="built_in">console</span>.log(test.padStart(<span class="number">8</span>,<span class="string">&#x27;.&#x27;</span>));    <span class="comment">// ...hello</span></span><br></pre></td></tr></table></figure></li>
<li>padEnd()：同上，只不过改成在后面补充</li>
</ol>
<blockquote>
<p>字符串大小转换</p>
</blockquote>
<ol>
<li>toLowerCase()、toUpperCase()：分别为转化为小写、转化为大写</li>
<li>toLocaleLowerCase()、toLocaleUpperCase()：分别为转化为小写、转化为大写<blockquote>
<p>两者的区别在于：后者会根据不同地方，进行特定的转换。</p>
</blockquote>
</li>
</ol>
<blockquote>
<p>字符串模式匹配：</p>
</blockquote>
<ol>
<li><p>match()：返回结果是<code>一个数组</code>，与<code>RegExp</code>的<code>exec()</code>返回的数组一样。所以用法也基本一样。<br></p>
 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;cat bat sat fat&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> result = text.match(<span class="regexp">/at/g</span>);</span><br></pre></td></tr></table></figure></li>
<li><p>search()：返回结果是<code>第一个匹配的位置索引</code>，使用方法与<code>match()</code>一致。<br></p>
 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;cat bat sat fat&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> result = text.match(<span class="regexp">/sat/</span>); </span><br><span class="line"><span class="built_in">console</span>.log(result);  <span class="comment">// 8</span></span><br></pre></td></tr></table></figure></li>
<li><p>replace()：返回一个<code>字符串副本</code>，第一个参数是<code>被替换目标</code>：可以是正则表达式、也可以是字符串。第二个参数是<code>替换字符串</code>;<br></p>
 <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;cat bat sat fat&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> result = text.replace(<span class="regexp">/at/</span>,<span class="string">&quot;ond&quot;</span>);  <span class="comment">// 只替换一个</span></span><br><span class="line"><span class="built_in">console</span>.log(result);  <span class="comment">//  cond bat sat fat </span></span><br><span class="line">      </span><br><span class="line"><span class="keyword">let</span> result = text.replace(<span class="regexp">/at/g</span>,<span class="string">&quot;ond&quot;</span>);  <span class="comment">// 全部替换</span></span><br><span class="line"><span class="built_in">console</span>.log(result);  <span class="comment">//  cond bond sond fond</span></span><br></pre></td></tr></table></figure>
<blockquote>
<p>对于replace而言，第二个参数可有<code>几个特殊的字符串序列</code>：<br></p>
</blockquote>
</li>
</ol>
  <figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> text = <span class="string">&quot;cat bat sat fat&quot;</span>;</span><br><span class="line"><span class="keyword">let</span> result = text.replace(<span class="regexp">/(.at)/g</span>,<span class="string">&quot;word($1)&quot;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(result);  <span class="comment">// word(cat) word(bat) word(sat) word(fat)</span></span><br></pre></td></tr></table></figure>
  <table>
    <tr>
      <td>字符串序列</td><td>替换的文本含义</td>
    </tr>
    <tr>
      <td>$$</td><td>$</td>
    </tr>
    <tr>
      <td>$&</td><td>匹配整个模式的子字符串。与RegExp.lastMatch相同</td>
    </tr>
    <tr>
      <td>$'</td><td>匹配的子字符串之前的字符串。与RegExp.rigthContext相同</td>
    </tr>
    <tr>
      <td>$`</td><td>匹配的字符串之后的字符串。与RegExp.leftContext相同</td>
    </tr>
    <tr>
      <td>$n</td><td>匹配第n个捕获组的字符串，n=0~9。如果没有捕获组则为空字符串</td>
    </tr>
    <tr>
      <td>$nn</td><td>匹配第n个捕获组的字符串，n=01~99。如果没有捕获组则为空字符串</td>
    </tr>
  </table>

<blockquote>
<p>关于字符串比较的方法：</p>
</blockquote>
<ol>
<li>localeCompare()：大于返回1、小于返回-1、等于返回0;</li>
</ol>
<h3 id="5-4-单例内置对象"><a href="#5-4-单例内置对象" class="headerlink" title="5.4 单例内置对象"></a>5.4 单例内置对象</h3><h4 id="5-4-1-Global"><a href="#5-4-1-Global" class="headerlink" title="5.4.1 Global"></a>5.4.1 Global</h4><blockquote>
<p><code>Global</code>是一个兜底对象，其实不存在于全局变量、全局函数，这些全局变量、全局函数都是<code>Global</code>对象属性、方法。</p>
</blockquote>
<blockquote>
<p><code>Global</code>部分方法：</p>
</blockquote>
<ol>
<li><p>URL编码方法</p>
</li>
<li><p>eval()方法</p>
</li>
</ol>
<blockquote>
<p><code>Global</code>属性：</p>
</blockquote>
<ul>
<li>undefined：特殊值undefined</li>
<li>NaN： 特殊值NaN</li>
<li>Infinity： 特殊值Infinity</li>
<li>Object： Object的构造函数</li>
<li>Array： Array的构造函数</li>
<li>Function： Function的构造函数</li>
<li>Boolean： Boolean的构造函数</li>
<li>String： String的构造函数</li>
<li>Number： Number的构造函数</li>
<li>Date： Date的构造函数</li>
<li>RegExp： RegExp的构造函数</li>
<li>Symbol： Symbol的伪构造函数Error Error的构造函数</li>
<li>EvalError： EvalError的构造函数</li>
<li>RangeError： RangeError的构造函数</li>
<li>ReferenceError： ReferenceError的构造函数</li>
<li>SyntaxError： SyntaxError的构造函数</li>
<li>TypeError： TypeError的构造函数</li>
<li>URIError： URIError的构造函数</li>
</ul>
<blockquote>
<p><code>Global</code>对象的浏览器代理——<code>window</code>对象【后面12章会详细讲解】</p>
</blockquote>
<h4 id="5-4-2-Math"><a href="#5-4-2-Math" class="headerlink" title="5.4.2 Math"></a>5.4.2 Math</h4><blockquote>
<p>Math对象，保存数学公式、信息和计算的地方。因为Math对象使用了JavaScript引擎中更高效的实现和处理指令，所以比直接在JavaScript中实现要<code>快得多</code>。</p>
</blockquote>
<blockquote>
<p>Math的属性</p>
</blockquote>
<ul>
<li>Math.E： 自然对数的基数e的值</li>
<li>Math.LN10： 10为底的自然对数</li>
<li>Math.LN2： 2为底的自然对数</li>
<li>Math.LOG2E： 以2为底e的对数</li>
<li>Math.LOG10E： 以10为底e的对数</li>
<li>Math.PI： π的值</li>
<li>Math.SQRT1_2： 1/2的平方根</li>
<li>Math.SQRT2： 2的平方根</li>
</ul>
<blockquote>
<p>Math的一些方法：</p>
</blockquote>
<ul>
<li>Math.min()和max():返回参数中，最小、最大的值</li>
<li>Math.ceil()：<code>向上舍入</code>为最接近的整数</li>
<li>Math.floor()：<code>向下舍入</code>为最接近的整数</li>
<li>Math.round()：<code>四舍五入</code></li>
<li>Math.fround()：返回最接近<code>单精度（32位）浮点值</code>表示</li>
<li>Math.random()：返回一个[0,1)的随机数。</li>
<li>Math.abs(x)： 返回x的绝对值</li>
<li>Math.exp(x)： 返回Math.E的x次幂</li>
<li>Math.expm1(x)： 等于Math.exp(x) - 1</li>
<li>Math.log(x)： 返回x的自然对数</li>
<li>Math.log1p(x)： 等于1 + Math.log(x)</li>
<li>Math.pow(x, power)： 返回x的power次幂</li>
<li>Math.hypot(…nums)： 返回nums中每个数平方和的平方根</li>
<li>Math.clz32(x)： 返回32位整数x的前置零的数量Math.sign(x) 返回表示x符号的1、 0、 -0或-1</li>
<li>Math.trunc(x)： 返回x的整数部分， 删除所有小数</li>
<li>Math.sqrt(x)： 返回x的平方根</li>
<li>Math.cbrt(x)： 返回x的立方根</li>
<li>Math.acos(x)： 返回x的反余弦</li>
<li>Math.acosh(x)： 返回x的反双曲余弦</li>
<li>Math.asin(x)： 返回x的反正弦</li>
<li>Math.asinh(x)： 返回x的反双曲正弦</li>
<li>Math.atan(x)： 返回x的反正切</li>
<li>Math.atanh(x)： 返回x的反双曲正切</li>
<li>Math.atan2(y, x)： 返回y/x的反正切</li>
<li>Math.cos(x)： 返回x的余弦</li>
<li>Math.sin(x)： 返回x的正弦</li>
<li>Math.tan(x)：返回x的正切</li>
</ul>
 
      <!-- reward -->
      
    </div>
    

    <!-- copyright -->
    
    <div class="declare">
      <ul class="post-copyright">
        <li>
          <i class="ri-copyright-line"></i>
          <strong>Copyright： </strong>
          
          Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
          
        </li>
      </ul>
    </div>
    
    <footer class="article-footer">
       
<div class="share-btn">
      <span class="share-sns share-outer">
        <i class="ri-share-forward-line"></i>
        分享
      </span>
      <div class="share-wrap">
        <i class="arrow"></i>
        <div class="share-icons">
          
          <a class="weibo share-sns" href="javascript:;" data-type="weibo">
            <i class="ri-weibo-fill"></i>
          </a>
          <a class="weixin share-sns wxFab" href="javascript:;" data-type="weixin">
            <i class="ri-wechat-fill"></i>
          </a>
          <a class="qq share-sns" href="javascript:;" data-type="qq">
            <i class="ri-qq-fill"></i>
          </a>
          <a class="douban share-sns" href="javascript:;" data-type="douban">
            <i class="ri-douban-line"></i>
          </a>
          <!-- <a class="qzone share-sns" href="javascript:;" data-type="qzone">
            <i class="icon icon-qzone"></i>
          </a> -->
          
          <a class="facebook share-sns" href="javascript:;" data-type="facebook">
            <i class="ri-facebook-circle-fill"></i>
          </a>
          <a class="twitter share-sns" href="javascript:;" data-type="twitter">
            <i class="ri-twitter-fill"></i>
          </a>
          <a class="google share-sns" href="javascript:;" data-type="google">
            <i class="ri-google-fill"></i>
          </a>
        </div>
      </div>
</div>

<div class="wx-share-modal">
    <a class="modal-close" href="javascript:;"><i class="ri-close-circle-line"></i></a>
    <p>扫一扫，分享到微信</p>
    <div class="wx-qrcode">
      <img src="//api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://example.com/2022/02/13/JavaScript%E5%AD%A6%E4%B9%A0/%E3%80%8AJavaScript%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E3%80%8B-%20%E7%AC%AC%E4%BA%94%E7%AB%A0%EF%BC%9A%E5%9F%BA%E6%9C%AC%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/" alt="微信分享二维码">
    </div>
</div>

<div id="share-mask"></div>  
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/JavaScript/" rel="tag">JavaScript</a></li></ul>

    </footer>
  </div>

   
  <nav class="article-nav">
    
      <a href="/2022/02/14/JavaScript%E5%AD%A6%E4%B9%A0/%E3%80%8AJavaScript%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E3%80%8B-%20%E7%AC%AC%E5%85%AD%E7%AB%A0%EF%BC%9A%E9%9B%86%E5%90%88%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B/" class="article-nav-link">
        <strong class="article-nav-caption">上一篇</strong>
        <div class="article-nav-title">
          
            《JavaScript高级程序设计》- 第六章：集合引用类型
          
        </div>
      </a>
    
    
      <a href="/2022/02/12/JavaScript%E5%AD%A6%E4%B9%A0/%E3%80%8AJavaScript%E9%AB%98%E7%BA%A7%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E3%80%8B-%20%E7%AC%AC%E5%9B%9B%E7%AB%A0%EF%BC%9A%E5%8F%98%E9%87%8F%E3%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E5%86%85%E5%AD%98/" class="article-nav-link">
        <strong class="article-nav-caption">下一篇</strong>
        <div class="article-nav-title">《JavaScript高级程序设计》- 第四章：变量、作用域与内存</div>
      </a>
    
  </nav>

   
<!-- valine评论 -->
<div id="vcomments-box">
  <div id="vcomments"></div>
</div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js"></script>
<script>
  new Valine({
    el: "#vcomments",
    app_id: "jeb2pvxjdeJQOj5OG3AUavGv-gzGzoHsz",
    app_key: "6YlB9tQJTstHMM8GOwFu4uyY",
    path: window.location.pathname,
    avatar: "monsterid",
    placeholder: "给我的文章加点评论吧~",
    recordIP: true,
  });
  const infoEle = document.querySelector("#vcomments .info");
  if (infoEle && infoEle.childNodes && infoEle.childNodes.length > 0) {
    infoEle.childNodes.forEach(function (item) {
      item.parentNode.removeChild(item);
    });
  }
</script>
<style>
  #vcomments-box {
    padding: 5px 30px;
  }

  @media screen and (max-width: 800px) {
    #vcomments-box {
      padding: 5px 0px;
    }
  }

  #vcomments-box #vcomments {
    background-color: #fff;
  }

  .v .vlist .vcard .vh {
    padding-right: 20px;
  }

  .v .vlist .vcard {
    padding-left: 10px;
  }
</style>

 
   
     
</article>

</section>
      <footer class="footer">
  <div class="outer">
    <ul>
      <li>
        Copyrights &copy;
        2022
        <i class="ri-heart-fill heart_icon"></i> 子与子乘
      </li>
    </ul>
    <ul>
      <li>
        
      </li>
    </ul>
    <ul>
      <li>
        
        
        <span>
  <span><i class="ri-user-3-fill"></i>Visitors:<span id="busuanzi_value_site_uv"></span></span>
  <span class="division">|</span>
  <span><i class="ri-eye-fill"></i>Views:<span id="busuanzi_value_page_pv"></span></span>
</span>
        
      </li>
    </ul>
    <ul>
      
    </ul>
    <ul>
      
    </ul>
    <ul>
      <li>
        <!-- cnzz统计 -->
        
      </li>
    </ul>
  </div>
</footer>    
    </main>
    <div class="float_btns">
      <div class="totop" id="totop">
  <i class="ri-arrow-up-line"></i>
</div>

<div class="todark" id="todark">
  <i class="ri-moon-line"></i>
</div>

    </div>
    <aside class="sidebar on">
      <button class="navbar-toggle"></button>
<nav class="navbar">
  
  <div class="logo">
    <a href="/"><img src="/images/ayer-side.svg" alt="欢迎"></a>
  </div>
  
  <ul class="nav nav-main">
    
    <li class="nav-item">
      <a class="nav-item-link" href="/">主页</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/archives">归档</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/categories">分类</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/tags">标签</a>
    </li>
    
    <li class="nav-item">
      <a class="nav-item-link" href="/friends">友链</a>
    </li>
    
  </ul>
</nav>
<nav class="navbar navbar-bottom">
  <ul class="nav">
    <li class="nav-item">
      
      <a class="nav-item-link nav-item-search"  title="Search">
        <i class="ri-search-line"></i>
      </a>
      
      
    </li>
  </ul>
</nav>
<div class="search-form-wrap">
  <div class="local-search local-search-plugin">
  <input type="search" id="local-search-input" class="local-search-input" placeholder="Search...">
  <div id="local-search-result" class="local-search-result"></div>
</div>
</div>
    </aside>
    <div id="mask"></div>

<!-- #reward -->
<div id="reward">
  <span class="close"><i class="ri-close-line"></i></span>
  <p class="reward-p"><i class="ri-cup-line"></i></p>
  <div class="reward-box">
    
    
  </div>
</div>
    
<script src="/js/jquery-3.6.0.min.js"></script>
 
<script src="/js/lazyload.min.js"></script>

<!-- Tocbot -->
 
<script src="/js/tocbot.min.js"></script>

<script>
  tocbot.init({
    tocSelector: ".tocbot",
    contentSelector: ".article-entry",
    headingSelector: "h1, h2, h3, h4, h5, h6",
    hasInnerContainers: true,
    scrollSmooth: true,
    scrollContainer: "main",
    positionFixedSelector: ".tocbot",
    positionFixedClass: "is-position-fixed",
    fixedSidebarOffset: "auto",
  });
</script>

<script src="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.js"></script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/jquery-modal@0.9.2/jquery.modal.min.css"
/>
<script src="https://cdn.jsdelivr.net/npm/justifiedGallery@3.7.0/dist/js/jquery.justifiedGallery.min.js"></script>

<script src="/dist/main.js"></script>

<!-- ImageViewer -->
 <!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">

    <!-- Background of PhotoSwipe. 
         It's a separate element as animating opacity is faster than rgba(). -->
    <div class="pswp__bg"></div>

    <!-- Slides wrapper with overflow:hidden. -->
    <div class="pswp__scroll-wrap">

        <!-- Container that holds slides. 
            PhotoSwipe keeps only 3 of them in the DOM to save memory.
            Don't modify these 3 pswp__item elements, data is added later on. -->
        <div class="pswp__container">
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
            <div class="pswp__item"></div>
        </div>

        <!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
        <div class="pswp__ui pswp__ui--hidden">

            <div class="pswp__top-bar">

                <!--  Controls are self-explanatory. Order can be changed. -->

                <div class="pswp__counter"></div>

                <button class="pswp__button pswp__button--close" title="Close (Esc)"></button>

                <button class="pswp__button pswp__button--share" style="display:none" title="Share"></button>

                <button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>

                <button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>

                <!-- Preloader demo http://codepen.io/dimsemenov/pen/yyBWoR -->
                <!-- element will get class pswp__preloader--active when preloader is running -->
                <div class="pswp__preloader">
                    <div class="pswp__preloader__icn">
                        <div class="pswp__preloader__cut">
                            <div class="pswp__preloader__donut"></div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
                <div class="pswp__share-tooltip"></div>
            </div>

            <button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
            </button>

            <button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
            </button>

            <div class="pswp__caption">
                <div class="pswp__caption__center"></div>
            </div>

        </div>

    </div>

</div>

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/default-skin/default-skin.min.css">
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/photoswipe@4.1.3/dist/photoswipe-ui-default.min.js"></script>

<script>
    function viewer_init() {
        let pswpElement = document.querySelectorAll('.pswp')[0];
        let $imgArr = document.querySelectorAll(('.article-entry img:not(.reward-img)'))

        $imgArr.forEach(($em, i) => {
            $em.onclick = () => {
                // slider展开状态
                // todo: 这样不好，后面改成状态
                if (document.querySelector('.left-col.show')) return
                let items = []
                $imgArr.forEach(($em2, i2) => {
                    let img = $em2.getAttribute('data-idx', i2)
                    let src = $em2.getAttribute('data-target') || $em2.getAttribute('src')
                    let title = $em2.getAttribute('alt')
                    // 获得原图尺寸
                    const image = new Image()
                    image.src = src
                    items.push({
                        src: src,
                        w: image.width || $em2.width,
                        h: image.height || $em2.height,
                        title: title
                    })
                })
                var gallery = new PhotoSwipe(pswpElement, PhotoSwipeUI_Default, items, {
                    index: parseInt(i)
                });
                gallery.init()
            }
        })
    }
    viewer_init()
</script> 
<!-- MathJax -->

<!-- Katex -->

<!-- busuanzi  -->
 
<script src="/js/busuanzi-2.3.pure.min.js"></script>
 
<!-- ClickLove -->

<!-- ClickBoom1 -->

<!-- ClickBoom2 -->

<!-- CodeCopy -->
 
<link rel="stylesheet" href="/css/clipboard.css">
 <script src="https://cdn.jsdelivr.net/npm/clipboard@2/dist/clipboard.min.js"></script>
<script>
  function wait(callback, seconds) {
    var timelag = null;
    timelag = window.setTimeout(callback, seconds);
  }
  !function (e, t, a) {
    var initCopyCode = function(){
      var copyHtml = '';
      copyHtml += '<button class="btn-copy" data-clipboard-snippet="">';
      copyHtml += '<i class="ri-file-copy-2-line"></i><span>COPY</span>';
      copyHtml += '</button>';
      $(".highlight .code pre").before(copyHtml);
      $(".article pre code").before(copyHtml);
      var clipboard = new ClipboardJS('.btn-copy', {
        target: function(trigger) {
          return trigger.nextElementSibling;
        }
      });
      clipboard.on('success', function(e) {
        let $btn = $(e.trigger);
        $btn.addClass('copied');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-checkbox-circle-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPIED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-checkbox-circle-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
      clipboard.on('error', function(e) {
        e.clearSelection();
        let $btn = $(e.trigger);
        $btn.addClass('copy-failed');
        let $icon = $($btn.find('i'));
        $icon.removeClass('ri-file-copy-2-line');
        $icon.addClass('ri-time-line');
        let $span = $($btn.find('span'));
        $span[0].innerText = 'COPY FAILED';
        
        wait(function () { // 等待两秒钟后恢复
          $icon.removeClass('ri-time-line');
          $icon.addClass('ri-file-copy-2-line');
          $span[0].innerText = 'COPY';
        }, 2000);
      });
    }
    initCopyCode();
  }(window, document);
</script>
 
<!-- CanvasBackground -->

<script>
  if (window.mermaid) {
    mermaid.initialize({ theme: "forest" });
  }
</script>


    
    

  </div>
</body>

</html>